/**
 * Beijing Jiaotong University
 * Copyright (c) 1896-2016 All Rights Reserved.
 */
package com.fesc.trade.demo.service;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.NameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fesc.trade.demo.constant.Constants;
import com.fesc.trade.demo.model.ExtendParams;
import com.fesc.trade.demo.model.GoodsDetail;
import com.fesc.trade.demo.model.RoyaltyDetailInfos;
import com.fesc.trade.demo.model.RoyaltyInfo;
import com.fesc.trade.demo.request.CancelRequest;
import com.fesc.trade.demo.request.CreateRequest;
import com.fesc.trade.demo.request.PayRequest;
import com.fesc.trade.demo.request.PreCreateRequest;
import com.fesc.trade.demo.request.QueryRequest;
import com.fesc.trade.demo.request.RefundQueryRequest;
import com.fesc.trade.demo.request.RefundRequest;
import com.fesc.trade.demo.util.DateUtil;
import com.fesc.trade.demo.util.HttpUtil;
import com.fesc.trade.demo.util.SecurityUtil;

/**
 * 
 * @author HuHui
 * @version $Id: TradeServiceImpl.java, v 0.1 2016年8月18日 下午12:32:12 HuHui Exp $
 */
public class TradeServiceImpl implements TradeService {

    /** 日志 */
    private static final Logger logger = LoggerFactory.getLogger(TradeServiceImpl.class);

    @Override
    public String pay() {

        /*******************公共参数********************/

        // (必填)收单机构编号
        String acquirerId = "10880010001";

        // (必填)签名类型 
        String signType = "RSA";

        // (必填)签名
        String sign = "";//根据参数生成

        // (必填)发送请求时间
        String timestamp = DateUtil.getNewFormatDateString(new Date());

        // 应用授权令牌, 第三方应用授权时填写，根据真实值填写
        String appAuthToken = "";

        // (必填)付款渠道
        String walletType = "alipay";

        /*******************业务参数********************/

        // (必填) 商户标识号
        String merchantId = "16360816504";

        // (必填) 商户网站订单系统中唯一订单号，32个字符以内，只能包含字母、数字、下划线，
        String outTradeNo = "tradepay" + System.currentTimeMillis() + (long) (Math.random() * 10000000L);

        // (必填) 支付场景
        String scene = "bar_code";

        // (必填) 订单标题，粗略描述用户的支付目的。如“xxx品牌xxx门店消费”
        String subject = "xxx品牌xxx门店当面付消费";

        // (必填) 订单总金额，单位为元，不能超过1亿元
        // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
        String totalAmount = "0.01";

        // (必填) 付款条码，用户支付宝钱包手机app点击“付款”产生的付款条码
        String authCode = "281662756949692365"; // 已用条码

        // (可选，根据需要决定是否使用) 订单可打折金额，可以配合商家平台配置折扣活动，如果订单部分商品参与打折，可以将部分商品总价填写至此字段，默认全部商品可打折
        // 如果该值未传入,但传入了【订单总金额】,【不可打折金额】 则该值默认为【订单总金额】- 【不可打折金额】
        //        String discountableAmount = "1.00"; //

        // (可选) 订单不可打折金额，可以配合商家平台配置折扣活动，如果酒水不参与打折，则将对应金额填写至此字段
        // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
        String undiscountableAmount = "0.0";

        // 卖家支付宝账号ID，用于支持一个签约账号下支持打款到不同的收款账号，(打款到sellerId对应的支付宝账号)
        // 如果该字段为空，则默认为与支付宝签约的商户的PID，也就是appid对应的PID
        String sellerId = "";

        // 订单描述，可以对交易或商品进行一个详细地描述，比如填写"购买商品3件共20.00元"
        String body = "购买商品3件共20.00元";

        // 商户操作员编号，添加此参数可以为商户操作员做销售统计
        String operatorId = "test_operator_id";

        // 商户门店编号，通过门店号和商家后台可以配置精准到门店的折扣信息，详询支付宝技术支持
        String storeId = "test_store_id";

        // 业务扩展参数，目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法)，详情请咨询支付宝技术支持
        String providerId = "2088100200300400500";
        ExtendParams extendParams = new ExtendParams();
        extendParams.setSysServiceProviderId(providerId);

        // 支付超时，线下扫码交易定义为5分钟
        String timeoutExpress = "5m";

        // 商品明细列表，需填写购买商品详细信息，
        List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();
        // 创建一个商品信息，参数含义分别为商品id（使用国标）、名称、单价（单位为分）、数量，如果需要添加商品类别，详见GoodsDetail
        GoodsDetail goods1 = GoodsDetail.newInstance("goods_id001", "xxx面包", "0.1", 1);
        // 创建好一个商品后添加至商品明细列表
        goodsDetailList.add(goods1);

        // 继续创建并添加第一条商品信息，用户购买的产品为“黑人牙刷”，单价为5.00元，购买了两件
        GoodsDetail goods2 = GoodsDetail.newInstance("goods_id002", "xxx牙刷", "0", 2);
        goodsDetailList.add(goods2);

        /**************************封装参数******************************/
        PayRequest payRequest = new PayRequest();

        payRequest.setAcquirerId(acquirerId);
        payRequest.setSignType(signType);
        payRequest.setTimestamp(timestamp);
        payRequest.setAppAuthToken(appAuthToken);
        payRequest.setWalletType(walletType);

        payRequest.setMerchantId(merchantId);
        payRequest.setOutTradeNo(outTradeNo);
        payRequest.setScene(scene);
        payRequest.setAuthCode(authCode);
        payRequest.setSellerId(sellerId);
        payRequest.setTotalAmount(totalAmount);
        payRequest.setSubject(subject);
        payRequest.setBody(body);
        payRequest.setGoodsDetailList(goodsDetailList);
        payRequest.setOperatorId(operatorId);
        payRequest.setStoreId(storeId);
        payRequest.setExtendParams(extendParams);
        payRequest.setTimeoutExpress(timeoutExpress);

        //生成签名
        Map<String, String> payRequestParaMap = payRequest.buildParaMap();

        String rsaSignStr;
        try {
            rsaSignStr = SecurityUtil.rsaSign(payRequestParaMap, Constants.ENCODE_PRIVATE_KEY, StandardCharsets.UTF_8.displayName());
        } catch (Exception e) {
            throw new RuntimeException("加签失败", e);
        }

        payRequestParaMap.put(Constants.SIGN, rsaSignStr);

        //参数验证
        payRequest.setSign(rsaSignStr);
        payRequest.validate();

        List<NameValuePair> paraList = HttpUtil.buildPostParaList(payRequestParaMap);

        String response = HttpUtil.httpClientPost(Constants.TEST_PAY_URL, paraList);

        return response;
    }

    @Override
    public String refund() {

        /*******************公共参数********************/

        // (必填)收单机构编号
        String acquirerId = "10880010001";

        // (必填)签名类型 
        String signType = "RSA";

        // (必填)签名
        String sign = "";//根据参数生成

        // (必填)发送请求时间
        String timestamp = DateUtil.getNewFormatDateString(new Date());

        // 应用授权令牌, 第三方应用授权时填写，根据真实值填写
        String appAuthToken = "";

        // (必填)付款渠道
        String walletType = "alipay";

        /*******************业务参数********************/

        // (必填) 商户标识号
        String merchantId = "16360816504";

        // 订单支付时传入的商户订单号,不能和 trade_no同时为空。
        String outTradeNo = "out_trade_no_1471509789775";

        // 支付宝交易号，和商户订单号不能同时为空
        String tradeNo = "";

        // 需要退款的金额，该金额不能大于订单金额,单位为元，支持两位小数
        String refundAmount = "0.01";

        // 退款的原因说明
        String refundReason = "";

        // 标识一次退款请求，同一笔交易多次退款需要保证唯一，如需部分退款，则此参数必传
        String outRequestNo = "";

        // 商户的操作员编号
        String operatorId = "";

        // 商户的门店编号
        String storeId = "";

        // 商户的终端编号
        String terminalId = "";

        // 扩展信息
        String externalInfo = "";

        /**************************封装参数******************************/
        RefundRequest refundRequest = new RefundRequest();

        refundRequest.setAcquirerId(acquirerId);
        refundRequest.setSignType(signType);
        refundRequest.setTimestamp(timestamp);
        refundRequest.setAppAuthToken(appAuthToken);
        refundRequest.setWalletType(walletType);

        refundRequest.setMerchantId(merchantId);
        refundRequest.setOutTradeNo(outTradeNo);
        refundRequest.setTradeNo(tradeNo);
        refundRequest.setRefundAmount(refundAmount);
        refundRequest.setRefundReason(refundReason);
        refundRequest.setOutRequestNo(outRequestNo);
        refundRequest.setOperatorId(operatorId);
        refundRequest.setStoreId(storeId);
        refundRequest.setTerminalId(terminalId);
        refundRequest.setExternalInfo(externalInfo);

        //生成签名
        Map<String, String> refundRequestParaMap = refundRequest.buildParaMap();

        String rsaSignStr;
        try {
            rsaSignStr = SecurityUtil.rsaSign(refundRequestParaMap, Constants.ENCODE_PRIVATE_KEY, StandardCharsets.UTF_8.displayName());
        } catch (Exception e) {
            throw new RuntimeException("加签失败", e);
        }

        refundRequestParaMap.put("sign", rsaSignStr);

        //参数验证
        refundRequest.setSign(rsaSignStr);
        refundRequest.validate();

        List<NameValuePair> paraList = HttpUtil.buildPostParaList(refundRequestParaMap);

        String response = HttpUtil.httpClientPost(Constants.TEST_REFUND_URL, paraList);

        return response;

    }

    public String create() {

        /*******************公共参数********************/

        // (必填)收单机构编号
        String acquirerId = "10880010001";

        // (必填)签名类型 
        String signType = "RSA";

        // (必填)签名
        String sign = "";//根据参数生成

        // (必填)发送请求时间
        String timestamp = DateUtil.getNewFormatDateString(new Date());

        // 应用授权令牌, 第三方应用授权时填写，根据真实值填写
        String appAuthToken = "";

        // (必填)付款渠道
        String walletType = "alipay";

        // (必填) 通知收单机构服务器里指定的页面http路径。
        String notify_url = "http://api.test.alipay.net/atinterface/receive_notify.htm";

        /*******************业务参数********************/

        // (必填) 商户标识号
        String merchantId = "16360816504";

        // (必填) 商户网站订单系统中唯一订单号，32个字符以内，只能包含字母、数字、下划线，
        String outTradeNo = "tradepay" + System.currentTimeMillis() + (long) (Math.random() * 10000000L);

        // 卖家支付宝账号ID，用于支持一个签约账号下支持打款到不同的收款账号，(打款到sellerId对应的支付宝账号)
        // 如果该字段为空，则默认为与支付宝签约的商户的PID，也就是appid对应的PID
        String sellerId = "";

        // (必填) 订单总金额，单位为元，不能超过1亿元
        // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
        String totalAmount = "0.01";

        // (可选，根据需要决定是否使用) 订单可打折金额，可以配合商家平台配置折扣活动，如果订单部分商品参与打折，可以将部分商品总价填写至此字段，默认全部商品可打折
        // 如果该值未传入,但传入了【订单总金额】,【不可打折金额】 则该值默认为【订单总金额】- 【不可打折金额】
        String discountableAmount = "0.01";

        // (可选) 订单不可打折金额，可以配合商家平台配置折扣活动，如果酒水不参与打折，则将对应金额填写至此字段
        // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
        String undiscountableAmount = "0.0";

        // (特殊) 买家支付宝账号，和buyer_id不能同时为空，测试时填写实际支付宝账号
        String buyerLogonId = "";

        // (必填) 订单标题，粗略描述用户的支付目的。如“xxx品牌xxx门店消费”
        String subject = "xxx品牌xxx门店当面付消费";

        // (可选)订单描述，可以对交易或商品进行一个详细地描述，比如填写"购买商品3件共20.00元"
        String body = "购买商品3件共20.00元";

        // (特殊) 买家的支付宝唯一用户号（2088开头的16位纯数字）,和buyer_logon_id不能同时为空
        String buyerId = "";

        // (可选)商品明细列表，需填写购买商品详细信息，
        List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();
        // 创建一个商品信息，参数含义分别为商品id（使用国标）、名称、单价（单位为分）、数量，如果需要添加商品类别，详见GoodsDetail
        GoodsDetail goods1 = GoodsDetail.newInstance("goods_id001", "xxx面包", "0.1", 1);
        // 创建好一个商品后添加至商品明细列表
        goodsDetailList.add(goods1);

        // 继续创建并添加第一条商品信息，用户购买的产品为“黑人牙刷”，单价为5.00元，购买了两件
        GoodsDetail goods2 = GoodsDetail.newInstance("goods_id002", "xxx牙刷", "0", 2);
        goodsDetailList.add(goods2);

        // (可选)商户操作员编号，添加此参数可以为商户操作员做销售统计
        String operatorId = "test_operator_id";

        // (可选)商户门店编号，通过门店号和商家后台可以配置精准到门店的折扣信息，详询支付宝技术支持
        String storeId = "test_store_id";

        // (可选)商户机具终端编号
        String terminalId = "";

        // (可选)业务扩展参数，目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法)，详情请咨询支付宝技术支持
        String providerId = "2088100200300400500";
        ExtendParams extendParams = new ExtendParams();
        extendParams.setSysServiceProviderId(providerId);

        // 支付超时，线下扫码交易定义为5分钟
        String timeoutExpress = "5m";

        // (可选)描述分账信息，json格式
        RoyaltyInfo royaltyInfo = new RoyaltyInfo();
        royaltyInfo.setRoyaltyType("ROYALTY");
        RoyaltyDetailInfos detailInfo1 = new RoyaltyDetailInfos();
        RoyaltyDetailInfos detailInfo2 = new RoyaltyDetailInfos();
        detailInfo1.setBatch_no("1");
        detailInfo1.setAmount("1.0");
        detailInfo1.setTrans_out_type("userId");
        detailInfo1.setTrans_out("2088101126765726");
        detailInfo1.setTrans_in("2088101126708402");
        detailInfo2.setBatch_no("2");
        detailInfo2.setAmount("2.0");
        detailInfo2.setTrans_out_type("userId");
        detailInfo2.setTrans_out("2088101126765726");
        detailInfo2.setTrans_in("2088101126708402");
        RoyaltyDetailInfos[] royaltyDetailInfos = { detailInfo1, detailInfo2 };
        royaltyInfo.setRoyaltyDetailInfos(royaltyDetailInfos);

        // (可选)扩展信息
        String externalInfo = "";

        /**************************封装参数******************************/
        CreateRequest createRequest = new CreateRequest();

        createRequest.setAcquirerId(acquirerId);
        createRequest.setSignType(signType);
        createRequest.setTimestamp(timestamp);
        createRequest.setAppAuthToken(appAuthToken);
        createRequest.setWalletType(walletType);
        createRequest.setNotify_url(notify_url);

        createRequest.setMerchantId(merchantId);
        createRequest.setOutTradeNo(outTradeNo);
        createRequest.setSellerId(sellerId);
        createRequest.setTotalAmount(totalAmount);
        createRequest.setUndiscountableAmount(undiscountableAmount);
        createRequest.setDiscountableAmount(discountableAmount);
        createRequest.setBuyerLogonID(buyerLogonId);
        createRequest.setBuyerId(buyerId);
        createRequest.setSubject(subject);
        createRequest.setBody(body);
        createRequest.setGoodsDetailList(goodsDetailList);
        createRequest.setOperatorId(operatorId);
        createRequest.setStoreId(storeId);
        createRequest.setTerminalId(terminalId);
        createRequest.setExtendParams(extendParams);
        createRequest.setRoyaltyInfo(royaltyInfo);
        createRequest.setTimeoutExpress(timeoutExpress);
        createRequest.setExternalInfo(externalInfo);

        //生成签名
        Map<String, String> createRequestParaMap = createRequest.buildParaMap();

        String rsaSignStr;
        try {
            rsaSignStr = SecurityUtil.rsaSign(createRequestParaMap, Constants.ENCODE_PRIVATE_KEY, StandardCharsets.UTF_8.displayName());
        } catch (Exception e) {
            throw new RuntimeException("加签失败", e);
        }

        //参数验证
        createRequest.setSign(rsaSignStr);
        createRequest.validate();

        createRequestParaMap.put(Constants.SIGN, rsaSignStr);

        List<NameValuePair> paraList = HttpUtil.buildPostParaList(createRequestParaMap);

        String response = HttpUtil.httpClientPost(Constants.TEST_CREATE_URL, paraList);

        return response;
    }

    @Override
    public String precreate() {

        /*******************公共参数********************/

        // (必填)收单机构编号
        String acquirerId = "10880010001";

        // (必填)签名类型 
        String signType = "RSA";

        // (必填)签名
        String sign = "";//根据参数生成

        // (必填)发送请求时间
        String timestamp = DateUtil.getNewFormatDateString(new Date());

        // 应用授权令牌, 第三方应用授权时填写，根据真实值填写
        String appAuthToken = "";

        // (必填)付款渠道
        String walletType = "alipay";

        // (必填) 通知URL
        String notify_url = "http://api.test.alipay.net/atinterface/receive_notify.htm";

        /*******************业务参数********************/

        // (必填) 商户标识号
        String merchantId = "16360816504";

        // (必填) 商户网站订单系统中唯一订单号，32个字符以内，只能包含字母、数字、下划线，
        String outTradeNo = "tradepay" + System.currentTimeMillis() + (long) (Math.random() * 10000000L);

        // 卖家支付宝账号ID，用于支持一个签约账号下支持打款到不同的收款账号，(打款到sellerId对应的支付宝账号)
        // 如果该字段为空，则默认为与支付宝签约的商户的PID，也就是appid对应的PID
        String sellerId = "";

        // (必填) 订单总金额，单位为元，不能超过1亿元
        // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
        String totalAmount = "0.01";

        // (可选，根据需要决定是否使用) 订单可打折金额，可以配合商家平台配置折扣活动，如果订单部分商品参与打折，可以将部分商品总价填写至此字段，默认全部商品可打折
        // 如果该值未传入,但传入了【订单总金额】,【不可打折金额】 则该值默认为【订单总金额】- 【不可打折金额】
        String discountableAmount = "0.01"; //

        // (可选) 订单不可打折金额，可以配合商家平台配置折扣活动，如果酒水不参与打折，则将对应金额填写至此字段
        // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
        String undiscountableAmount = "0.0";

        // (可选) 买家支付宝账号
        String buyerLogonId = "";

        // (必填) 订单标题，粗略描述用户的支付目的。如“xxx品牌xxx门店消费”
        String subject = "xxx品牌xxx门店当面付消费";

        // 订单描述，可以对交易或商品进行一个详细地描述，比如填写"购买商品3件共20.00元"
        String body = "购买商品3件共20.00元";

        // (可选)商品明细列表，需填写购买商品详细信息，
        List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();
        // 创建一个商品信息，参数含义分别为商品id（使用国标）、名称、单价（单位为分）、数量，如果需要添加商品类别，详见GoodsDetail
        GoodsDetail goods1 = GoodsDetail.newInstance("goods_id001", "xxx面包", "1", 1);
        // 创建好一个商品后添加至商品明细列表
        goodsDetailList.add(goods1);

        // 继续创建并添加第一条商品信息，用户购买的产品为“黑人牙刷”，单价为5.00元，购买了两件
        GoodsDetail goods2 = GoodsDetail.newInstance("goods_id002", "xxx牙刷", "5", 2);
        goodsDetailList.add(goods2);

        // (可选)商户操作员编号，添加此参数可以为商户操作员做销售统计
        String operatorId = "test_operator_id";

        // (可选)商户门店编号，通过门店号和商家后台可以配置精准到门店的折扣信息，详询支付宝技术支持
        String storeId = "test_store_id";

        // (可选)商户机具终端编号
        String terminalId = "";

        // (可选)业务扩展参数，目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法)，详情请咨询支付宝技术支持
        String providerId = "2088100200300400500";
        ExtendParams extendParams = new ExtendParams();
        extendParams.setSysServiceProviderId(providerId);

        // 支付超时，线下扫码交易定义为5分钟
        String timeoutExpress = "5m";

        // (可选)描述分账信息，json格式
        RoyaltyInfo royaltyInfo = new RoyaltyInfo();
        royaltyInfo.setRoyaltyType("ROYALTY");
        RoyaltyDetailInfos detailInfo1 = new RoyaltyDetailInfos();
        RoyaltyDetailInfos detailInfo2 = new RoyaltyDetailInfos();
        detailInfo1.setBatch_no("1");
        detailInfo1.setAmount("1.0");
        detailInfo1.setTrans_out_type("userId");
        detailInfo1.setTrans_out("2088101126765726");
        detailInfo1.setTrans_in("2088101126708402");
        detailInfo2.setBatch_no("2");
        detailInfo2.setAmount("2.0");
        detailInfo2.setTrans_out_type("userId");
        detailInfo2.setTrans_out("2088101126765726");
        detailInfo2.setTrans_in("2088101126708402");
        RoyaltyDetailInfos[] royaltyDetailInfos = { detailInfo1, detailInfo2 };
        royaltyInfo.setRoyaltyDetailInfos(royaltyDetailInfos);

        // (可选)扩展信息
        String externalInfo = "";

        /**************************封装参数******************************/
        PreCreateRequest precreateRequest = new PreCreateRequest();

        precreateRequest.setAcquirerId(acquirerId);
        precreateRequest.setSignType(signType);
        precreateRequest.setTimestamp(timestamp);
        precreateRequest.setAppAuthToken(appAuthToken);
        precreateRequest.setWalletType(walletType);
        precreateRequest.setNotify_url(notify_url);

        precreateRequest.setMerchantId(merchantId);
        precreateRequest.setOutTradeNo(outTradeNo);
        precreateRequest.setSellerId(sellerId);
        precreateRequest.setTotalAmount(totalAmount);
        precreateRequest.setUndiscountableAmount(undiscountableAmount);
        precreateRequest.setDiscountableAmount(discountableAmount);
        precreateRequest.setBuyerLogonID(buyerLogonId);
        precreateRequest.setSubject(subject);
        precreateRequest.setBody(body);
        precreateRequest.setGoodsDetailList(goodsDetailList);
        precreateRequest.setOperatorId(operatorId);
        precreateRequest.setStoreId(storeId);
        precreateRequest.setTerminalId(terminalId);
        precreateRequest.setExtendParams(extendParams);
        precreateRequest.setRoyaltyInfo(royaltyInfo);
        precreateRequest.setTimeoutExpress(timeoutExpress);
        precreateRequest.setExternalInfo(externalInfo);

        //生成签名
        Map<String, String> precreateRequestParaMap = precreateRequest.buildParaMap();

        String rsaSignStr;
        try {
            rsaSignStr = SecurityUtil.rsaSign(precreateRequestParaMap, Constants.ENCODE_PRIVATE_KEY, StandardCharsets.UTF_8.displayName());
        } catch (Exception e) {
            throw new RuntimeException("加签失败", e);
        }

        precreateRequestParaMap.put(Constants.SIGN, rsaSignStr);

        //参数验证
        precreateRequest.setSign(rsaSignStr);
        precreateRequest.validate();

        List<NameValuePair> paraList = HttpUtil.buildPostParaList(precreateRequestParaMap);

        String response = HttpUtil.httpClientPost(Constants.TEST_PRECREATE_URL, paraList);

        return response;
    }

    @Override
    public String query() {

        /*******************公共参数********************/

        // (必填)收单机构编号
        String acquirerId = "10880010001";

        // (必填)签名类型 
        String signType = "RSA";

        // (必填)签名
        String sign = "";//根据参数生成

        // (必填)发送请求时间
        String timestamp = DateUtil.getNewFormatDateString(new Date());

        // 应用授权令牌, 第三方应用授权时填写，根据真实值填写
        String appAuthToken = "";

        // (必填)付款渠道
        String walletType = "alipay";

        /*******************业务参数********************/
        // (必填) 商户标识号
        String merchantId = "16360816504";

        // (可选) 商户网站订单系统中唯一订单号，32个字符以内，与交易号不能同时为空
        String outTradeNo = "tradepay14726267385904413146";

        // (可选)支付宝交易号，和商户订单号不能同时为空
        String tradeNo = "";

        // (可选)扩展信息
        String externalInfo = "";

        /**************************封装参数******************************/
        QueryRequest queryRequest = new QueryRequest();

        queryRequest.setAcquirerId(acquirerId);
        queryRequest.setSignType(signType);
        queryRequest.setTimestamp(timestamp);
        queryRequest.setAppAuthToken(appAuthToken);
        queryRequest.setWalletType(walletType);

        queryRequest.setMerchantId(merchantId);
        queryRequest.setOutTradeNo(outTradeNo);
        queryRequest.setTradeNo(tradeNo);
        queryRequest.setExternalInfo(externalInfo);

        //生成签名
        Map<String, String> queryRequestParaMap = queryRequest.buildParaMap();

        String rsaSignStr;
        try {
            rsaSignStr = SecurityUtil.rsaSign(queryRequestParaMap, Constants.ENCODE_PRIVATE_KEY, StandardCharsets.UTF_8.displayName());
        } catch (Exception e) {
            throw new RuntimeException("加签失败", e);
        }

        queryRequestParaMap.put(Constants.SIGN, rsaSignStr);

        //参数验证
        queryRequest.setSign(rsaSignStr);
        queryRequest.validate();

        List<NameValuePair> paraList = HttpUtil.buildPostParaList(queryRequestParaMap);

        String response = HttpUtil.httpClientPost(Constants.TEST_QUERY_URL, paraList);

        return response;

    }

    @Override
    public String refundQuery() {

        /*******************公共参数********************/

        // (必填)收单机构编号
        String acquirerId = "10880010033";

        // (必填)签名类型 
        String signType = "RSA";

        // (必填)签名
        String sign = "";//根据参数生成

        // (必填)发送请求时间
        String timestamp = DateUtil.getNewFormatDateString(new Date());

        // 应用授权令牌, 第三方应用授权时填写，根据真实值填写
        String appAuthToken = "";

        // (必填)付款渠道
        String walletType = "alipay";

        /*******************业务参数********************/
        // (必填) 商户标识号
        String merchantId = "16360816504";

        // (可选) 商户网站订单系统中唯一订单号，32个字符以内，与交易号不能同时为空
        String outTradeNo = "out_trade_no_147090774139911100";

        // (可选)支付宝交易号，和商户订单号不能同时为空
        String tradeNo = "";

        // (必填)请求退款接口时，传入的退款请求号
        String outRequestNo = "out_request_no_1470919465785";

        // (可选)扩展信息
        String externalInfo = "";

        /**************************封装参数******************************/
        RefundQueryRequest refundQueryRequest = new RefundQueryRequest();

        refundQueryRequest.setAcquirerId(acquirerId);
        refundQueryRequest.setSignType(signType);
        refundQueryRequest.setTimestamp(timestamp);
        refundQueryRequest.setAppAuthToken(appAuthToken);
        refundQueryRequest.setWalletType(walletType);

        refundQueryRequest.setMerchantId(merchantId);
        refundQueryRequest.setOutTradeNo(outTradeNo);
        refundQueryRequest.setTradeNo(tradeNo);
        refundQueryRequest.setOutRequestNo(outRequestNo);
        refundQueryRequest.setExternalInfo(externalInfo);

        //生成签名
        Map<String, String> refundQueryRequestParaMap = refundQueryRequest.buildParaMap();

        String rsaSignStr;
        try {
            rsaSignStr = SecurityUtil.rsaSign(refundQueryRequestParaMap, Constants.ENCODE_PRIVATE_KEY, StandardCharsets.UTF_8.displayName());
        } catch (Exception e) {
            throw new RuntimeException("加签失败", e);
        }

        refundQueryRequestParaMap.put(Constants.SIGN, rsaSignStr);

        //参数验证
        refundQueryRequest.setSign(rsaSignStr);
        refundQueryRequest.validate();

        List<NameValuePair> paraList = HttpUtil.buildPostParaList(refundQueryRequestParaMap);

        String response = HttpUtil.httpClientPost(Constants.TEST_REFUND_QUERY_URL, paraList);

        return response;
    }

    @Override
    public String cancel() {

        /*******************公共参数********************/

        // (必填)收单机构编号
        String acquirerId = "10880010001";

        // (必填)签名类型 
        String signType = "RSA";

        // (必填)签名
        String sign = "";//根据参数生成

        // (必填)发送请求时间
        String timestamp = DateUtil.getNewFormatDateString(new Date());

        // 应用授权令牌, 第三方应用授权时填写，根据真实值填写
        String appAuthToken = "";

        // (必填)付款渠道
        String walletType = "alipay";

        /*******************业务参数********************/
        // (必填) 商户标识号
        String merchantId = "16360816504";

        // (可选) 商户网站订单系统中唯一订单号，32个字符以内，与交易号不能同时为空
        String outTradeNo = "out_trade_no_1471509789775";

        // (可选)支付宝交易号，和商户订单号不能同时为空
        String tradeNo = "";

        // (可选)扩展信息
        String externalInfo = "";

        /**************************封装参数******************************/
        CancelRequest cancelRequest = new CancelRequest();

        cancelRequest.setAcquirerId(acquirerId);
        cancelRequest.setSignType(signType);
        cancelRequest.setTimestamp(timestamp);
        cancelRequest.setAppAuthToken(appAuthToken);
        cancelRequest.setWalletType(walletType);

        cancelRequest.setMerchantId(merchantId);
        cancelRequest.setOutTradeNo(outTradeNo);
        cancelRequest.setTradeNo(tradeNo);
        cancelRequest.setExternalInfo(externalInfo);

        //生成签名
        Map<String, String> cancelRequestParaMap = cancelRequest.buildParaMap();

        String rsaSignStr;
        try {
            rsaSignStr = SecurityUtil.rsaSign(cancelRequestParaMap, Constants.ENCODE_PRIVATE_KEY, StandardCharsets.UTF_8.displayName());
        } catch (Exception e) {
            throw new RuntimeException("加签失败", e);
        }

        cancelRequestParaMap.put(Constants.SIGN, rsaSignStr);

        //参数验证
        cancelRequest.setSign(rsaSignStr);
        cancelRequest.validate();

        List<NameValuePair> paraList = HttpUtil.buildPostParaList(cancelRequestParaMap);

        String response = HttpUtil.httpClientPost(Constants.TEST_CANCEL_URL, paraList);

        return response;
    }

}
